package com.nineclock.approve.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.approve.dto.*;
import com.nineclock.approve.mapper.ApproveDefinitionMapper;
import com.nineclock.approve.pojo.ApproveDefinition;
import com.nineclock.approve.service.ActivitiService;
import com.nineclock.approve.service.ApproveDefinitionService;
import com.nineclock.approve.utils.ApproveExtendsUtils;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.UUIDUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class ApproveDefinitionServiceImpl implements ApproveDefinitionService {

    @Autowired
    private ApproveDefinitionMapper approveDefinitionMapper;

    @Autowired
    private ActivitiService activitiService;

    @Override
    public List<ApproveGroupDefinitionDto> queryApproveGroupDefinition() {

        // 1.获取当前登录用户的公司id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        // 2.查询当前公司所有的流程定义信息
        LambdaQueryWrapper<ApproveDefinition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ApproveDefinition::getCompanyId, companyId);
        wrapper.eq(ApproveDefinition::getIsValid, "1");
        List<ApproveDefinition> approveDefinitionList = approveDefinitionMapper.selectList(wrapper);

        // 3.数据转换
        if(!CollectionUtils.isEmpty(approveDefinitionList)){

            List<ApproveGroupDefinitionDto> resultList = new ArrayList<>();

            // 将查询出来的列表按照类型进行分组，key为groupType, value为这个类型下的流程定义列表
            Map<String, List<ApproveDefinition>> map = approveDefinitionList.stream().collect(
                    Collectors.groupingBy(ApproveDefinition::getGroupType));


            for (String groupType : map.keySet()) {
                ApproveGroupDefinitionDto approveGroupDefinitionDto = new ApproveGroupDefinitionDto();
                approveGroupDefinitionDto.setGroupType(groupType);
                approveGroupDefinitionDto.setDefinitionList(map.get(groupType));
                resultList.add(approveGroupDefinitionDto);
            }
            return resultList;

        }
        return null;
    }

    @Override
    public void saveApproveDefinition(ApproveDefinitionDto approveDefinitionDto) {
        // 1.参数校验
        if(approveDefinitionDto == null || approveDefinitionDto.getBaseData() == null
            || CollectionUtils.isEmpty(approveDefinitionDto.getTableData())
            || StringUtils.isEmpty(approveDefinitionDto.getFlowData())){

            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 2.保存数据
        ApproveDefinitionBaseDataDto baseData = approveDefinitionDto.getBaseData();

        if(StringUtils.isEmpty(baseData.getId())){ // 新增

            // 2.1 保存基本信息
            ApproveDefinition approveDefinition = BeanHelper.copyProperties(baseData, ApproveDefinition.class);
            approveDefinition.setCompanyId(CurrentUserHolder.get().getCompanyId().toString());
            approveDefinition.setCreateTime(new Date());
            approveDefinition.setUpdateTime(new Date());
            approveDefinition.setTableName("flow" + UUIDUtils.getUUID());
            approveDefinition.setIsValid("1");

            // 2.2 调用公共方法，设置流程其他信息
            setApproveDefinitionInfo(approveDefinitionDto, baseData, approveDefinition);

            approveDefinitionMapper.insert(approveDefinition);

            // 2.3 将流程定义信息部署到activiti
            activitiService.deployProcessToActiviti(approveDefinition);


        } else { // 修改

            // 保存基本信息
            ApproveDefinition approveDefinition = BeanHelper.copyProperties(baseData, ApproveDefinition.class);
            approveDefinition.setUpdateTime(new Date());
            approveDefinition.setTableName("flow" + UUIDUtils.getUUID());

            // 调用公共方法，设置流程其他信息
            setApproveDefinitionInfo(approveDefinitionDto, baseData, approveDefinition);

            approveDefinitionMapper.updateById(approveDefinition);

            // 删除Activiti原本的流程定义信息
            activitiService.deleteProcessToActiviti(approveDefinition);

            // 将流程定义信息部署到activiti
            activitiService.deployProcessToActiviti(approveDefinition);
        }

    }

    /**
     * 公共方法，设置流程相关信息
     * @param approveDefinitionDto
     * @param baseData
     * @param approveDefinition
     */
    private void setApproveDefinitionInfo(ApproveDefinitionDto approveDefinitionDto, ApproveDefinitionBaseDataDto baseData, ApproveDefinition approveDefinition) {
        // 2.2 设置谁可以发起审批
        List<AllowUserObjDto> allowUserJson = baseData.getAllowUserJson();
        if(!CollectionUtils.isEmpty(allowUserJson)){
            approveDefinition.setAllowUserJson(JSON.toJSONString(allowUserJson));
        }

        // 2.3 设置表单数据
        List<ApproveDefinitionTableDataDto> tableData = approveDefinitionDto.getTableData();
        if(!CollectionUtils.isEmpty(tableData)){
            approveDefinition.setFormJson(JSON.toJSONString(tableData));

            // 额外设置collum字段，将表单数据每个元素添加一个fieldKey的值
            List<ColumnObjDto> columns = ApproveExtendsUtils.getClolumnListWithFieldKey(approveDefinitionDto);
            approveDefinition.setColumns(JSON.toJSONString(columns));
        }

        // 2.4 设置流程数据
        String flowData = approveDefinitionDto.getFlowData();
        JSONArray jsonArray = JSON.parseArray(flowData);
        ApproveExtendsUtils.expandParamWithNodeKey(jsonArray);
        approveDefinition.setFlowJson(JSON.toJSONString(jsonArray));
    }

    @Override
    public ApproveDefinitionDto queryById(String id) {
        // 1.根据id查询流程定义信息
        ApproveDefinition approveDefinition = approveDefinitionMapper.selectById(id);

        // 2.数据封装
        ApproveDefinitionDto approveDefinitionDto = new ApproveDefinitionDto();

        // 2.1 封装基本信息
        ApproveDefinitionBaseDataDto baseData = BeanHelper.copyProperties(approveDefinition,
                ApproveDefinitionBaseDataDto.class);
        approveDefinitionDto.setBaseData(baseData);
        
        // 2.2 封装表单数据
        String formJson = approveDefinition.getFormJson();
        List<ApproveDefinitionTableDataDto> tableData = JSON.parseArray(formJson, ApproveDefinitionTableDataDto.class);
        approveDefinitionDto.setTableData(tableData);

        // 2.3 封装流程数据
        approveDefinitionDto.setFlowData(approveDefinition.getFlowJson());

        return approveDefinitionDto;
    }
}
